package com.supermarket.config.filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * 请求体日志过滤器
 * 用于记录请求体内容
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestBodyLogFilter implements Filter {

    private static final List<String> LOGGABLE_CONTENT_TYPES = Arrays.asList(
            "application/json", 
            "application/xml", 
            "application/x-www-form-urlencoded",
            "text/plain"
    );
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        
        // 检查是否为HTTP请求
        if (!(request instanceof HttpServletRequest)) {
            chain.doFilter(request, response);
            return;
        }
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String method = httpRequest.getMethod();
        String contentType = httpRequest.getContentType();
        
        // 只对POST和PUT请求以及特定内容类型进行处理
        boolean shouldLogBody = ("POST".equals(method) || "PUT".equals(method)) && 
                               contentType != null && 
                               isLoggableContentType(contentType);
        
        if (shouldLogBody) {
            // 使用包装器缓存请求体
            ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(httpRequest);
            ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((jakarta.servlet.http.HttpServletResponse) response);
            
            try {
                // 执行过滤器链
                chain.doFilter(requestWrapper, responseWrapper);
                
                // 记录请求体
                byte[] content = requestWrapper.getContentAsByteArray();
                if (content.length > 0) {
                    String requestBody = new String(content, StandardCharsets.UTF_8);
                    System.out.println("\n请求体内容: " + requestBody);
                }
            } finally {
                // 确保响应内容被正确复制到原始响应
                responseWrapper.copyBodyToResponse();
            }
        } else {
            // 不需要记录请求体的情况，直接传递请求
            chain.doFilter(request, response);
        }
    }
    
    private boolean isLoggableContentType(String contentType) {
        return LOGGABLE_CONTENT_TYPES.stream()
                .anyMatch(contentType.toLowerCase()::contains);
    }
} 